home *** CD-ROM | disk | FTP | other *** search
/ X User Tools / X User Tools (O'Reilly and Associates)(1994).ISO / sources / libxpm / libxpm34.gz / libxpm34 / xpm-3.4 / lib / create.c next >
C/C++ Source or Header  |  1994-03-14  |  38KB  |  1,418 lines

  1. /* Copyright 1989-94 GROUPE BULL -- See license conditions in file COPYRIGHT */
  2. /*****************************************************************************\
  3. * create.c:                                                                   *
  4. *                                                                             *
  5. *  XPM library                                                                *
  6. *  Create an X image and possibly its related shape mask                      *
  7. *  from the given xpmInternAttrib.                                            *
  8. *                                                                             *
  9. *  Developed by Arnaud Le Hors                                                *
  10. \*****************************************************************************/
  11.  
  12. #include "xpmP.h"
  13. #ifdef VMS
  14. #include "sys$library:ctype.h"
  15. #else
  16. #include <ctype.h>
  17. #endif
  18.  
  19. LFUNC(xpmVisualType, int, (Visual *visual));
  20.  
  21. LFUNC(SetCloseColor, int, (Display *display, Colormap colormap,
  22.                Visual *visual, XColor *col,
  23.                Pixel *image_pixel, Pixel *mask_pixel,
  24.                Pixel **pixels, unsigned int *npixels,
  25.                XpmAttributes *attributes,
  26.                XColor *cols, int ncols));
  27.  
  28. LFUNC(SetColor, int, (Display *display, Colormap colormap, Visual *visual,
  29.               char *colorname, unsigned int color_index,
  30.               Pixel *image_pixel, Pixel *mask_pixel,
  31.               unsigned int *mask_pixel_index, Pixel **pixels,
  32.               unsigned int *npixels, XpmAttributes *attributes,
  33.               XColor *cols, int ncols));
  34.  
  35. LFUNC(CreateXImage, int, (Display *display, Visual *visual,
  36.               unsigned int depth, unsigned int width,
  37.               unsigned int height, XImage **image_return));
  38.  
  39. LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes,
  40.               XpmColor *ct, unsigned int ncolors, Pixel *ip,
  41.               Pixel *mp, unsigned int *mask_pixel,
  42.               Pixel **pixels, unsigned int *npixels));
  43.  
  44. LFUNC(SetImagePixels, void, (XImage *image, unsigned int width,
  45.                  unsigned int height, unsigned int *pixelindex,
  46.                  Pixel *pixels));
  47.  
  48. LFUNC(SetImagePixels32, void, (XImage *image, unsigned int width,
  49.                    unsigned int height, unsigned int *pixelindex,
  50.                    Pixel *pixels));
  51.  
  52. LFUNC(SetImagePixels16, void, (XImage *image, unsigned int width,
  53.                    unsigned int height, unsigned int *pixelindex,
  54.                    Pixel *pixels));
  55.  
  56. LFUNC(SetImagePixels8, void, (XImage *image, unsigned int width,
  57.                   unsigned int height, unsigned int *pixelindex,
  58.                   Pixel *pixels));
  59.  
  60. LFUNC(SetImagePixels1, void, (XImage *image, unsigned int width,
  61.                   unsigned int height, unsigned int *pixelindex,
  62.                   Pixel *pixels));
  63.  
  64. #ifdef NEED_STRCASECMP
  65. LFUNC(strcasecmp, int, (char *s1, char *s2));
  66.  
  67. /*
  68.  * in case strcasecmp is not provided by the system here is one
  69.  * which does the trick
  70.  */
  71. static int
  72. strcasecmp(s1, s2)
  73.     register char *s1, *s2;
  74. {
  75.     register int c1, c2;
  76.  
  77.     while (*s1 && *s2) {
  78.     c1 = isupper(*s1) ? tolower(*s1) : *s1;
  79.     c2 = isupper(*s2) ? tolower(*s2) : *s2;
  80.     if (c1 != c2)
  81.         return (1);
  82.     s1++;
  83.     s2++;
  84.     }
  85.     if (*s1 || *s2)
  86.     return (1);
  87.     return (0);
  88. }
  89. #endif
  90.  
  91. /*
  92.  * return the default color key related to the given visual
  93.  */
  94. static int
  95. xpmVisualType(visual)
  96.     Visual *visual;
  97. {
  98.     switch (visual->class) {
  99.     case StaticGray:
  100.     case GrayScale:
  101.     switch (visual->map_entries) {
  102.     case 2:
  103.         return (XPM_MONO);
  104.     case 4:
  105.         return (XPM_GRAY4);
  106.     default:
  107.         return (XPM_GRAY);
  108.     }
  109.     default:
  110.     return (XPM_COLOR);
  111.     }
  112. }
  113.  
  114.  
  115. typedef struct {
  116.     int cols_index;
  117.     long closeness;
  118. }      CloseColor;
  119.  
  120. static int
  121. closeness_cmp(a, b)
  122.     void *a, *b;
  123. {
  124.     CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b;
  125.  
  126.     return (x->closeness - y->closeness);
  127. }
  128.  
  129. /*
  130.  * set a close color in case the exact one can't be set
  131.  * return 0 if success, 1 otherwise.
  132.  */
  133.  
  134. static int 
  135. SetCloseColor(display, colormap, visual, col, 
  136.           image_pixel, mask_pixel, pixels, npixels, attributes,
  137.         cols, ncols)
  138.     Display *display;
  139.     Colormap colormap;
  140.     Visual *visual;
  141.     XColor *col;
  142.     Pixel *image_pixel, *mask_pixel;
  143.     Pixel **pixels;
  144.     unsigned int *npixels;
  145.     XpmAttributes *attributes;
  146.     XColor *cols;
  147.     int ncols;
  148. {
  149.     /*
  150.      * Allocation failed, so try close colors. To get here the visual must
  151.      * be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor?
  152.      * What about sharing systems like QDSS?). Beware: we have to treat
  153.      * DirectColor differently.
  154.      */
  155.  
  156.  
  157.     long int red_closeness, green_closeness, blue_closeness;
  158.     int n;
  159.  
  160.     if (attributes && (attributes->valuemask & XpmCloseness))
  161.     red_closeness = green_closeness = blue_closeness =
  162.         attributes->closeness;
  163.     else {
  164.     red_closeness = attributes->red_closeness;
  165.     green_closeness = attributes->green_closeness;
  166.     blue_closeness = attributes->blue_closeness;
  167.     }
  168.  
  169.  
  170.     /*
  171.      * We sort the colormap by closeness and try to allocate the color
  172.      * closest to the target. If the allocation of this close color fails,
  173.      * which almost never happens, then one of two scenarios is possible.
  174.      * Either the colormap must have changed (since the last close color
  175.      * allocation or possibly while we were sorting the colormap), or the
  176.      * color is allocated as Read/Write by some other client. (Note: X
  177.      * _should_ allow clients to check if a particular color is Read/Write,
  178.      * but it doesn't! :-( ). We cannot determine which of these scenarios
  179.      * occurred, so we try the next closest color, and so on, until no more
  180.      * colors are within closeness of the target. If we knew that the
  181.      * colormap had changed, we could skip this sequence.
  182.      * 
  183.      * If _none_ of the colors within closeness of the target can be allocated,
  184.      * then we can finally be pretty sure that the colormap has actually
  185.      * changed. In this case we try to allocate the original color (again),
  186.      * then try the closecolor stuff (again)...
  187.      * 
  188.      * In theory it would be possible for an infinite loop to occur if another
  189.      * process kept changing the colormap every time we sorted it, so we set
  190.      * a maximum on the number of iterations. After this many tries, we use
  191.      * XGrabServer() to ensure that the colormap remains unchanged.
  192.      * 
  193.      * This approach gives particularly bad worst case performance - as many as
  194.      * <MaximumIterations> colormap reads and sorts may be needed, and as
  195.      * many as <MaximumIterations> * <ColormapSize> attempted allocations
  196.      * may fail. On an 8-bit system, this means as many as 3 colormap reads,
  197.      * 3 sorts and 768 failed allocations per execution of this code!
  198.      * Luckily, my experiments show that in general use in a typical 8-bit
  199.      * color environment only about 1 in every 10000 allocations fails to
  200.      * succeed in the fastest possible time. So virtually every time what
  201.      * actually happens is a single sort followed by a successful allocate.
  202.      * The very first allocation also costs a colormap read, but no further
  203.      * reads are usually necessary.
  204.      */
  205.  
  206. #define ITERATIONS 2            /* more than one is almost never
  207.                      * necessary */
  208.  
  209.     for (n = 0; n <= ITERATIONS; ++n) {
  210.     CloseColor *closenesses =
  211.     (CloseColor *) XpmCalloc(ncols, sizeof(CloseColor));
  212.     int i, c;
  213.  
  214.     for (i = 0; i < ncols; ++i) {    /* build & sort closenesses table */
  215. #define COLOR_FACTOR       3
  216. #define BRIGHTNESS_FACTOR  1
  217.  
  218.         closenesses[i].cols_index = i;
  219.         closenesses[i].closeness =
  220.         COLOR_FACTOR * (abs((long) col->red - (long) cols[i].red)
  221.                 + abs((long) col->green - (long) cols[i].green)
  222.                 + abs((long) col->blue - (long) cols[i].blue))
  223.             + BRIGHTNESS_FACTOR * abs(((long) col->red +
  224.                            (long) col->green +
  225.                            (long) col->blue)
  226.                           - ((long) cols[i].red +
  227.                          (long) cols[i].green +
  228.                          (long) cols[i].blue));
  229.     }
  230.     qsort(closenesses, ncols, sizeof(CloseColor), closeness_cmp);
  231.  
  232.     i = 0;
  233.     c = closenesses[i].cols_index;
  234.     while ((long) cols[c].red >= (long) col->red - red_closeness &&
  235.            (long) cols[c].red <= (long) col->red + red_closeness &&
  236.            (long) cols[c].green >= (long) col->green - green_closeness &&
  237.            (long) cols[c].green <= (long) col->green + green_closeness &&
  238.            (long) cols[c].blue >= (long) col->blue - blue_closeness &&
  239.            (long) cols[c].blue <= (long) col->blue + blue_closeness) {
  240.         if (XAllocColor(display, colormap, &cols[c])) {
  241.         if (n == ITERATIONS)
  242.             XUngrabServer(display);
  243.         XpmFree(closenesses);
  244.         *image_pixel = cols[c].pixel;
  245.         *mask_pixel = 1;
  246.         (*pixels)[*npixels] = cols[c].pixel;
  247.         (*npixels)++;
  248.         return (0);
  249.         } else {
  250.         ++i; if (i == ncols) break;
  251.         c = closenesses[i].cols_index;
  252.         }
  253.     }
  254.  
  255.     /* Couldn't allocate _any_ of the close colors! */
  256.  
  257.     if (n == ITERATIONS)
  258.         XUngrabServer(display);
  259.     XpmFree(closenesses);
  260.  
  261.     if (i == 0 || i == ncols)    /* no color close enough or cannot */
  262.         return (1);            /* alloc any color (full of r/w's) */
  263.  
  264.     if (XAllocColor(display, colormap, col)) {
  265.         *image_pixel = col->pixel;
  266.         *mask_pixel = 1;
  267.         (*pixels)[*npixels] = col->pixel;
  268.         (*npixels)++;
  269.         return (0);
  270.     } else {            /* colormap has probably changed, so
  271.                      * re-read... */
  272.         if (n == ITERATIONS - 1)
  273.         XGrabServer(display);
  274.  
  275. #if 0
  276.         if (visual->class == DirectColor) {
  277.         /* TODO */
  278.         } else
  279. #endif
  280.         XQueryColors(display, colormap, cols, ncols);
  281.     }
  282.     }
  283.     return (1);
  284. }
  285.  
  286. #define USE_CLOSECOLOR attributes && \
  287. (((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \
  288.  || ((attributes->valuemask & XpmRGBCloseness) && \
  289.      attributes->red_closeness != 0 \
  290.      && attributes->green_closeness != 0 \
  291.      && attributes->blue_closeness != 0))
  292.  
  293. /*
  294.  * set the color pixel related to the given colorname,
  295.  * return 0 if success, 1 otherwise.
  296.  */
  297.  
  298. static int
  299. SetColor(display, colormap, visual, colorname, color_index,
  300.      image_pixel, mask_pixel, mask_pixel_index,
  301.      pixels, npixels, attributes, cols, ncols)
  302.     Display *display;
  303.     Colormap colormap;
  304.     Visual *visual;
  305.     char *colorname;
  306.     unsigned int color_index;
  307.     Pixel *image_pixel, *mask_pixel;
  308.     unsigned int *mask_pixel_index;
  309.     Pixel **pixels;
  310.     unsigned int *npixels;
  311.     XpmAttributes *attributes;
  312.     XColor *cols;
  313.     int ncols;
  314. {
  315.     XColor xcolor;
  316.  
  317.     if (strcasecmp(colorname, TRANSPARENT_COLOR)) {
  318.     if (!XParseColor(display, colormap, colorname, &xcolor))
  319.         return (1);
  320.     if (!XAllocColor(display, colormap, &xcolor)) {
  321.         if (USE_CLOSECOLOR)
  322.         return (SetCloseColor(display, colormap, visual, &xcolor,
  323.                       image_pixel, mask_pixel, pixels, npixels,
  324.                       attributes, cols, ncols));
  325.         else
  326.         return (1);
  327.     }
  328.     *image_pixel = xcolor.pixel;
  329.     *mask_pixel = 1;
  330.     (*pixels)[*npixels] = xcolor.pixel;
  331.     (*npixels)++;
  332.     } else {
  333.     *image_pixel = 0;
  334.     *mask_pixel = 0;
  335.     *mask_pixel_index = color_index;/* store the color table index */
  336.     }
  337.     return (0);
  338. }
  339.  
  340.  
  341. static int
  342. CreateColors(display, attributes, ct, ncolors,
  343.          ip, mp, mask_pixel, pixels, npixels)
  344.     Display *display;
  345.     XpmAttributes *attributes;
  346.     XpmColor *ct;
  347.     unsigned int ncolors;
  348.     Pixel *ip;
  349.     Pixel *mp;
  350.     unsigned int *mask_pixel;        /* mask pixel index */
  351.     Pixel **pixels;            /* allocated pixels */
  352.     unsigned int *npixels;        /* number of allocated pixels */
  353. {
  354.     /* variables stored in the XpmAttributes structure */
  355.     Visual *visual;
  356.     Colormap colormap;
  357.     XpmColorSymbol *colorsymbols;
  358.     unsigned int numsymbols;
  359.  
  360.     char *colorname;
  361.     unsigned int a, b, l;
  362.     Boolean pixel_defined;
  363.     unsigned int key;
  364.     XpmColorSymbol *symbol;
  365.     char **defaults;
  366.     int ErrorStatus = XpmSuccess;
  367.     char *s;
  368.     int default_index;
  369.  
  370.     XColor *cols = NULL;
  371.     unsigned int ncols = 0;
  372.  
  373.     /*
  374.      * retrieve information from the XpmAttributes
  375.      */
  376.     if (attributes && attributes->valuemask & XpmColorSymbols) {
  377.     colorsymbols = attributes->colorsymbols;
  378.     numsymbols = attributes->numsymbols;
  379.     } else
  380.     numsymbols = 0;
  381.  
  382.     if (attributes && attributes->valuemask & XpmVisual)
  383.     visual = attributes->visual;
  384.     else
  385.     visual = DefaultVisual(display, DefaultScreen(display));
  386.  
  387.     if (attributes && attributes->valuemask & XpmColormap)
  388.     colormap = attributes->colormap;
  389.     else
  390.     colormap = DefaultColormap(display, DefaultScreen(display));
  391.  
  392.     if (attributes && attributes->valuemask & XpmColorKey)
  393.     key = attributes->color_key;
  394.     else
  395.     key = xpmVisualType(visual);
  396.  
  397.     if (USE_CLOSECOLOR) {
  398.     /* originally from SetCloseColor */
  399. #if 0
  400.     if (visual->class == DirectColor) {
  401.         /*
  402.          * TODO: Implement close colors for DirectColor visuals. This is
  403.          * difficult situation. Chances are that we will never get here,
  404.          * because any machine that supports DirectColor will probably
  405.          * also support TrueColor (and probably PseudoColor). Also,
  406.          * DirectColor colormaps can be very large, so looking for close
  407.          * colors may be too slow.
  408.          */
  409.     } else {
  410. #endif
  411.         int i;
  412.         ncols = visual->map_entries;
  413.         cols = (XColor *) XpmCalloc(ncols, sizeof(XColor));
  414.         for (i = 0; i < ncols; ++i)
  415.         cols[i].pixel = i;
  416.         XQueryColors(display, colormap, cols, ncols);
  417. #if 0
  418.     }
  419. #endif
  420.     }
  421.  
  422.     switch (key) {
  423.     case XPM_MONO:
  424.     default_index = 2;
  425.     break;
  426.     case XPM_GRAY4:
  427.     default_index = 3;
  428.     break;
  429.     case XPM_GRAY:
  430.     default_index = 4;
  431.     break;
  432.     case XPM_COLOR:
  433.     default:
  434.     default_index = 5;
  435.     break;
  436.     }
  437.  
  438.     for (a = 0; a < ncolors; a++, ct++, ip++, mp++) {
  439.     colorname = NULL;
  440.     pixel_defined = False;
  441.     defaults = (char **) ct;
  442.  
  443.     /*
  444.      * look for a defined symbol
  445.      */
  446.     if (numsymbols && defaults[1]) {
  447.         s = defaults[1];
  448.         for (l = 0, symbol = colorsymbols; l < numsymbols; l++, symbol++) {
  449.         if (symbol->name && s && !strcmp(symbol->name, s))
  450.             /* override name */
  451.             break;
  452.         if (!symbol->name && symbol->value) {    /* override value */
  453.             int def_index = default_index;
  454.  
  455.             while (defaults[def_index] == NULL)    /* find defined
  456.                              * colorname */
  457.             --def_index;
  458.             if (def_index < 2) {/* nothing towards mono, so try
  459.                      * towards color */
  460.             def_index = default_index + 1;
  461.             while (def_index <= 5 && defaults[def_index] == NULL)
  462.                 ++def_index;
  463.             }
  464.             if (def_index >= 2 && defaults[def_index] != NULL &&
  465.             !strcasecmp(symbol->value, defaults[def_index]))
  466.             break;
  467.         }
  468.         }
  469.         if (l != numsymbols) {
  470.         if (symbol->name && symbol->value)
  471.             colorname = symbol->value;
  472.         else
  473.             pixel_defined = True;
  474.         }
  475.     }
  476.     if (!pixel_defined) {        /* pixel not given as symbol value */
  477.         if (colorname) {        /* colorname given as symbol value */
  478.         if (!SetColor(display, colormap, visual, colorname, a, ip, mp,
  479.                   mask_pixel, pixels, npixels, attributes,
  480.                 cols, ncols))
  481.             pixel_defined = True;
  482.         else
  483.             ErrorStatus = XpmColorError;
  484.         }
  485.         b = key;
  486.         while (!pixel_defined && b > 1) {
  487.         if (defaults[b]) {
  488.             if (!SetColor(display, colormap, visual, defaults[b],
  489.                   a, ip, mp, mask_pixel, pixels, npixels,
  490.                   attributes, cols, ncols)) {
  491.             pixel_defined = True;
  492.             break;
  493.             } else
  494.             ErrorStatus = XpmColorError;
  495.         }
  496.         b--;
  497.         }
  498.         b = key + 1;
  499.         while (!pixel_defined && b < NKEYS + 1) {
  500.         if (defaults[b]) {
  501.             if (!SetColor(display, colormap, visual, defaults[b],
  502.                   a, ip, mp, mask_pixel, pixels, npixels,
  503.                   attributes, cols, ncols)) {
  504.             pixel_defined = True;
  505.             break;
  506.             } else
  507.             ErrorStatus = XpmColorError;
  508.         }
  509.         b++;
  510.         }
  511.         if (!pixel_defined) {
  512.         if (cols)
  513.             XpmFree(cols);
  514.         return (XpmColorFailed);
  515.         }
  516.     } else {
  517.         *ip = colorsymbols[l].pixel;
  518.         if (symbol->value
  519.         && !strcasecmp(symbol->value, TRANSPARENT_COLOR)) {
  520.         *mp = 0;
  521.         *mask_pixel = 0;
  522.         } else
  523.         *mp = 1;
  524.     }
  525.     }
  526.     if (cols)
  527.     XpmFree(cols);
  528.     return (ErrorStatus);
  529. }
  530.  
  531.  
  532. /* function call in case of error, frees only locally allocated variables */
  533. #undef RETURN
  534. #define RETURN(status) \
  535. { \
  536.     if (ximage) XDestroyImage(ximage); \
  537.     if (shapeimage) XDestroyImage(shapeimage); \
  538.     if (ximage_pixels) XpmFree(ximage_pixels); \
  539.     if (mask_pixels) XpmFree(mask_pixels); \
  540.     if (npixels) XFreeColors(display, colormap, pixels, npixels, 0); \
  541.     if (pixels) XpmFree(pixels); \
  542.     return (status); \
  543. }
  544.  
  545. int
  546. XpmCreateImageFromXpmImage(display, image,
  547.                image_return, shapeimage_return, attributes)
  548.     Display *display;
  549.     XpmImage *image;
  550.     XImage **image_return;
  551.     XImage **shapeimage_return;
  552.     XpmAttributes *attributes;
  553. {
  554.     /* variables stored in the XpmAttributes structure */
  555.     Visual *visual;
  556.     Colormap colormap;
  557.     unsigned int depth;
  558.  
  559.     /* variables to return */
  560.     XImage *ximage = NULL;
  561.     XImage *shapeimage = NULL;
  562.     unsigned int mask_pixel;
  563.     int ErrorStatus;
  564.  
  565.     /* calculation variables */
  566.     Pixel *ximage_pixels = NULL;
  567.     Pixel *mask_pixels = NULL;
  568.     Pixel *pixels = NULL;        /* allocated pixels */
  569.     unsigned int npixels = 0;        /* number of allocated pixels */
  570.  
  571.     /* initialize return values */
  572.     if (image_return)
  573.     *image_return = NULL;
  574.     if (shapeimage_return)
  575.     *shapeimage_return = NULL;
  576.  
  577.     /* retrieve information from the XpmAttributes */
  578.     if (attributes && (attributes->valuemask & XpmVisual))
  579.     visual = attributes->visual;
  580.     else
  581.     visual = DefaultVisual(display, DefaultScreen(display));
  582.  
  583.     if (attributes && (attributes->valuemask & XpmColormap))
  584.     colormap = attributes->colormap;
  585.     else
  586.     colormap = DefaultColormap(display, DefaultScreen(display));
  587.  
  588.     if (attributes && (attributes->valuemask & XpmDepth))
  589.     depth = attributes->depth;
  590.     else
  591.     depth = DefaultDepth(display, DefaultScreen(display));
  592.     ErrorStatus = XpmSuccess;
  593.  
  594.     /* malloc pixels index tables */
  595.     ximage_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
  596.     if (!ximage_pixels)
  597.     return (XpmNoMemory);
  598.  
  599.     mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
  600.     if (!mask_pixels)
  601.     RETURN(XpmNoMemory);
  602.  
  603.     mask_pixel = XpmUndefPixel;
  604.  
  605.     /* maximum of allocated pixels will be the number of colors */
  606.     pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
  607.     if (!pixels)
  608.     RETURN(XpmNoMemory);
  609.  
  610.     /* get pixel colors, store them in index tables */
  611.     ErrorStatus = CreateColors(display, attributes, image->colorTable,
  612.                    image->ncolors, ximage_pixels, mask_pixels,
  613.                    &mask_pixel, &pixels, &npixels);
  614.  
  615.     if (ErrorStatus != XpmSuccess
  616.     && (ErrorStatus < 0 || (attributes
  617.                 && (attributes->valuemask & XpmExactColors)
  618.                 && attributes->exactColors)))
  619.     RETURN(ErrorStatus);
  620.  
  621.     /* create the ximage */
  622.     if (image_return) {
  623.     ErrorStatus = CreateXImage(display, visual, depth,
  624.                    image->width, image->height, &ximage);
  625.     if (ErrorStatus != XpmSuccess)
  626.         RETURN(ErrorStatus);
  627.  
  628.     /*
  629.      * set the ximage data
  630.      * 
  631.      * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use
  632.      * optimized functions, otherwise use slower but sure general one.
  633.      * 
  634.      */
  635.  
  636.     if (ximage->depth == 1)
  637.         SetImagePixels1(ximage, image->width, image->height,
  638.                 image->data, ximage_pixels);
  639.     else if (ximage->bits_per_pixel == 8)
  640.         SetImagePixels8(ximage, image->width, image->height,
  641.                 image->data, ximage_pixels);
  642.     else if (ximage->bits_per_pixel == 16)
  643.         SetImagePixels16(ximage, image->width, image->height,
  644.                  image->data, ximage_pixels);
  645.     else if (ximage->bits_per_pixel == 32)
  646.         SetImagePixels32(ximage, image->width, image->height,
  647.                  image->data, ximage_pixels);
  648.     else
  649.         SetImagePixels(ximage, image->width, image->height,
  650.                image->data, ximage_pixels);
  651.     }
  652.  
  653.     /* create the shape mask image */
  654.     if (mask_pixel != XpmUndefPixel && shapeimage_return) {
  655.     ErrorStatus = CreateXImage(display, visual, 1, image->width,
  656.                    image->height, &shapeimage);
  657.     if (ErrorStatus != XpmSuccess)
  658.         RETURN(ErrorStatus);
  659.  
  660.     SetImagePixels1(shapeimage, image->width, image->height,
  661.             image->data, mask_pixels);
  662.     }
  663.     XpmFree(mask_pixels);
  664.     XpmFree(pixels);
  665.  
  666.     /* if requested store alloc'ed pixels in the XpmAttributes structure */
  667.     if (attributes) {
  668.     if (attributes->valuemask & XpmReturnPixels ||
  669. /* 3.2 backward compatibility code */
  670.         attributes->valuemask & XpmReturnInfos) {
  671. /* end 3.2 bc */
  672.         if (mask_pixel != XpmUndefPixel) {
  673.         Pixel *pixels, *p1, *p2;
  674.         unsigned int a;
  675.  
  676.         attributes->npixels = image->ncolors - 1;
  677.         pixels = (Pixel *) XpmMalloc(sizeof(Pixel)
  678.                          * attributes->npixels);
  679.         if (pixels) {
  680.             p1 = ximage_pixels;
  681.             p2 = pixels;
  682.             for (a = 0; a < image->ncolors; a++, p1++)
  683.             if (a != mask_pixel)
  684.                 *p2++ = *p1;
  685.             attributes->pixels = pixels;
  686.         } else {
  687.             /* if error just say we can't return requested data */
  688.             attributes->valuemask &= ~XpmReturnPixels;
  689. /* 3.2 backward compatibility code */
  690.             attributes->valuemask &= ~XpmReturnInfos;
  691. /* end 3.2 bc */
  692.             attributes->pixels = NULL;
  693.             attributes->npixels = 0;
  694.         }
  695.         XpmFree(ximage_pixels);
  696.         } else {
  697.         attributes->pixels = ximage_pixels;
  698.         attributes->npixels = image->ncolors;
  699.         }
  700.         attributes->mask_pixel = mask_pixel;
  701.     } else
  702.         XpmFree(ximage_pixels);
  703.     } else
  704.         XpmFree(ximage_pixels);
  705.  
  706.     /* return created images */
  707.     if (image_return)
  708.     *image_return = ximage;
  709.     if (shapeimage_return)
  710.     *shapeimage_return = shapeimage;
  711.  
  712.     return (ErrorStatus);
  713. }
  714.  
  715.  
  716. /*
  717.  * Create an XImage
  718.  */
  719. static int
  720. CreateXImage(display, visual, depth, width, height, image_return)
  721.     Display *display;
  722.     Visual *visual;
  723.     unsigned int depth;
  724.     unsigned int width;
  725.     unsigned int height;
  726.     XImage **image_return;
  727. {
  728.     int bitmap_pad;
  729.  
  730.     /* first get bitmap_pad */
  731.     if (depth > 16)
  732.     bitmap_pad = 32;
  733.     else if (depth > 8)
  734.     bitmap_pad = 16;
  735.     else
  736.     bitmap_pad = 8;
  737.  
  738.     /* then create the XImage with data = NULL and bytes_per_line = 0 */
  739.     *image_return = XCreateImage(display, visual, depth, ZPixmap, 0, 0,
  740.                  width, height, bitmap_pad, 0);
  741.     if (!*image_return)
  742.     return (XpmNoMemory);
  743.  
  744.     /* now that bytes_per_line must have been set properly alloc data */
  745.     (*image_return)->data =
  746.     (char *) XpmMalloc((*image_return)->bytes_per_line * height);
  747.  
  748.     if (!(*image_return)->data) {
  749.     XDestroyImage(*image_return);
  750.     *image_return = NULL;
  751.     return (XpmNoMemory);
  752.     }
  753.     return (XpmSuccess);
  754. }
  755.  
  756.  
  757. /*
  758.  * The functions below are written from X11R5 MIT's code (XImUtil.c)
  759.  *
  760.  * The idea is to have faster functions than the standard XPutPixel function
  761.  * to build the image data. Indeed we can speed up things by suppressing tests
  762.  * performed for each pixel. We do the same tests but at the image level.
  763.  * We also assume that we use only ZPixmap images with null offsets.
  764.  */
  765.  
  766. LFUNC(_putbits, void, (register char *src, int dstoffset,
  767.                register int numbits, register char *dst));
  768.  
  769. LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register int nb));
  770.  
  771.     static unsigned char Const _reverse_byte[0x100] = {
  772.     0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
  773.     0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
  774.     0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
  775.     0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
  776.     0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
  777.     0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
  778.     0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
  779.     0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
  780.     0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
  781.     0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
  782.     0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
  783.     0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
  784.     0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
  785.     0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
  786.     0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
  787.     0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
  788.     0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
  789.     0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
  790.     0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
  791.     0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
  792.     0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
  793.     0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
  794.     0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
  795.     0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
  796.     0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
  797.     0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
  798.     0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
  799.     0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
  800.     0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
  801.     0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
  802.     0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
  803.     0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
  804.     };
  805.  
  806.     static int
  807.         _XReverse_Bytes(bpt, nb)
  808.     register unsigned char *bpt;
  809.     register int nb;
  810. {
  811.     do {
  812.     *bpt = _reverse_byte[*bpt];
  813.     bpt++;
  814.     } while (--nb > 0);
  815.     return 0;
  816. }
  817.  
  818.  
  819. void
  820. xpm_xynormalizeimagebits(bp, img)
  821.     register unsigned char *bp;
  822.     register XImage *img;
  823. {
  824.     register unsigned char c;
  825.  
  826.     if (img->byte_order != img->bitmap_bit_order) {
  827.     switch (img->bitmap_unit) {
  828.  
  829.     case 16:
  830.         c = *bp;
  831.         *bp = *(bp + 1);
  832.         *(bp + 1) = c;
  833.         break;
  834.  
  835.     case 32:
  836.         c = *(bp + 3);
  837.         *(bp + 3) = *bp;
  838.         *bp = c;
  839.         c = *(bp + 2);
  840.         *(bp + 2) = *(bp + 1);
  841.         *(bp + 1) = c;
  842.         break;
  843.     }
  844.     }
  845.     if (img->bitmap_bit_order == MSBFirst)
  846.     _XReverse_Bytes(bp, img->bitmap_unit >> 3);
  847. }
  848.  
  849. void
  850. xpm_znormalizeimagebits(bp, img)
  851.     register unsigned char *bp;
  852.     register XImage *img;
  853. {
  854.     register unsigned char c;
  855.  
  856.     switch (img->bits_per_pixel) {
  857.  
  858.     case 2:
  859.     _XReverse_Bytes(bp, 1);
  860.     break;
  861.  
  862.     case 4:
  863.     *bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
  864.     break;
  865.  
  866.     case 16:
  867.     c = *bp;
  868.     *bp = *(bp + 1);
  869.     *(bp + 1) = c;
  870.     break;
  871.  
  872.     case 24:
  873.     c = *(bp + 2);
  874.     *(bp + 2) = *bp;
  875.     *bp = c;
  876.     break;
  877.  
  878.     case 32:
  879.     c = *(bp + 3);
  880.     *(bp + 3) = *bp;
  881.     *bp = c;
  882.     c = *(bp + 2);
  883.     *(bp + 2) = *(bp + 1);
  884.     *(bp + 1) = c;
  885.     break;
  886.     }
  887. }
  888.  
  889. static unsigned char Const _lomask[0x09] = {
  890. 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  891. static unsigned char Const _himask[0x09] = {
  892. 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
  893.  
  894. static void
  895. _putbits(src, dstoffset, numbits, dst)
  896.     register char *src;            /* address of source bit string */
  897.     int dstoffset;            /* bit offset into destination;
  898.                      * range is 0-31 */
  899.     register int numbits;        /* number of bits to copy to
  900.                      * destination */
  901.     register char *dst;            /* address of destination bit string */
  902. {
  903.     register unsigned char chlo, chhi;
  904.     int hibits;
  905.  
  906.     dst = dst + (dstoffset >> 3);
  907.     dstoffset = dstoffset & 7;
  908.     hibits = 8 - dstoffset;
  909.     chlo = *dst & _lomask[dstoffset];
  910.     for (;;) {
  911.     chhi = (*src << dstoffset) & _himask[dstoffset];
  912.     if (numbits <= hibits) {
  913.         chhi = chhi & _lomask[dstoffset + numbits];
  914.         *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
  915.         break;
  916.     }
  917.     *dst = chhi | chlo;
  918.     dst++;
  919.     numbits = numbits - hibits;
  920.     chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
  921.     src++;
  922.     if (numbits <= dstoffset) {
  923.         chlo = chlo & _lomask[numbits];
  924.         *dst = (*dst & _himask[numbits]) | chlo;
  925.         break;
  926.     }
  927.     numbits = numbits - dstoffset;
  928.     }
  929. }
  930.  
  931. /*
  932.  * Default method to write pixels into a Z image data structure.
  933.  * The algorithm used is:
  934.  *
  935.  *    copy the destination bitmap_unit or Zpixel to temp
  936.  *    normalize temp if needed
  937.  *    copy the pixel bits into the temp
  938.  *    renormalize temp if needed
  939.  *    copy the temp back into the destination image data
  940.  */
  941.  
  942. static void
  943. SetImagePixels(image, width, height, pixelindex, pixels)
  944.     XImage *image;
  945.     unsigned int width;
  946.     unsigned int height;
  947.     unsigned int *pixelindex;
  948.     Pixel *pixels;
  949. {
  950.     register char *src;
  951.     register char *dst;
  952.     register unsigned int *iptr;
  953.     register int x, y, i;
  954.     register char *data;
  955.     Pixel pixel, px;
  956.     int nbytes, depth, ibu, ibpp;
  957.  
  958.     data = image->data;
  959.     iptr = pixelindex;
  960.     depth = image->depth;
  961.     if (depth == 1) {
  962.     ibu = image->bitmap_unit;
  963.     for (y = 0; y < height; y++)
  964.         for (x = 0; x < width; x++, iptr++) {
  965.         pixel = pixels[*iptr];
  966.         for (i = 0, px = pixel; i < sizeof(unsigned long);
  967.              i++, px >>= 8)
  968.             ((unsigned char *) &pixel)[i] = px;
  969.         src = &data[XYINDEX(x, y, image)];
  970.         dst = (char *) &px;
  971.         px = 0;
  972.         nbytes = ibu >> 3;
  973.         for (i = nbytes; --i >= 0;)
  974.             *dst++ = *src++;
  975.         XYNORMALIZE(&px, image);
  976.         _putbits((char *) &pixel, (x % ibu), 1, (char *) &px);
  977.         XYNORMALIZE(&px, image);
  978.         src = (char *) &px;
  979.         dst = &data[XYINDEX(x, y, image)];
  980.         for (i = nbytes; --i >= 0;)
  981.             *dst++ = *src++;
  982.         }
  983.     } else {
  984.     ibpp = image->bits_per_pixel;
  985.     for (y = 0; y < height; y++)
  986.         for (x = 0; x < width; x++, iptr++) {
  987.         pixel = pixels[*iptr];
  988.         if (depth == 4)
  989.             pixel &= 0xf;
  990.         for (i = 0, px = pixel; i < sizeof(unsigned long); i++,
  991.              px >>= 8)
  992.             ((unsigned char *) &pixel)[i] = px;
  993.         src = &data[ZINDEX(x, y, image)];
  994.         dst = (char *) &px;
  995.         px = 0;
  996.         nbytes = (ibpp + 7) >> 3;
  997.         for (i = nbytes; --i >= 0;)
  998.             *dst++ = *src++;
  999.         ZNORMALIZE(&px, image);
  1000.         _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
  1001.         ZNORMALIZE(&px, image);
  1002.         src = (char *) &px;
  1003.         dst = &data[ZINDEX(x, y, image)];
  1004.         for (i = nbytes; --i >= 0;)
  1005.             *dst++ = *src++;
  1006.         }
  1007.     }
  1008. }
  1009.  
  1010. /*
  1011.  * write pixels into a 32-bits Z image data structure
  1012.  */
  1013.  
  1014. #ifndef WORD64
  1015. /* this item is static but deterministic so let it slide; doesn't
  1016. ** hurt re-entrancy of this library. Note if it is actually const then would
  1017. ** be OK under rules of ANSI-C but probably not C++ which may not
  1018. ** want to allocate space for it.
  1019. */
  1020. static unsigned long /*constant */ RTXpm_byteorderpixel = MSBFirst << 24;
  1021.  
  1022. #endif
  1023.  
  1024. /*
  1025.    WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original
  1026.    3.2e code - by default you get the speeded-up version.
  1027. */
  1028.  
  1029. static void
  1030. SetImagePixels32(image, width, height, pixelindex, pixels)
  1031.     XImage *image;
  1032.     unsigned int width;
  1033.     unsigned int height;
  1034.     unsigned int *pixelindex;
  1035.     Pixel *pixels;
  1036. {
  1037.     unsigned char *data;
  1038.     unsigned int *iptr;
  1039.     int y;
  1040.     Pixel pixel;
  1041.  
  1042. #ifdef WITHOUT_SPEEDUPS
  1043.  
  1044.     int x;
  1045.     unsigned char *addr;
  1046.  
  1047.     data = (unsigned char *) image->data;
  1048.     iptr = pixelindex;
  1049. #ifndef WORD64
  1050.     if (*((char *) &RTXpm_byteorderpixel) == image->byte_order) {
  1051.     for (y = 0; y < height; y++)
  1052.         for (x = 0; x < width; x++, iptr++) {
  1053.         addr = &data[ZINDEX32(x, y, image)];
  1054.         *((unsigned long *) addr) = pixels[*iptr];
  1055.         }
  1056.     } else
  1057. #endif
  1058.     if (image->byte_order == MSBFirst)
  1059.     for (y = 0; y < height; y++)
  1060.         for (x = 0; x < width; x++, iptr++) {
  1061.         addr = &data[ZINDEX32(x, y, image)];
  1062.         pixel = pixels[*iptr];
  1063.         addr[0] = pixel >> 24;
  1064.         addr[1] = pixel >> 16;
  1065.         addr[2] = pixel >> 8;
  1066.         addr[3] = pixel;
  1067.         }
  1068.     else
  1069.     for (y = 0; y < height; y++)
  1070.         for (x = 0; x < width; x++, iptr++) {
  1071.         addr = &data[ZINDEX32(x, y, image)];
  1072.         pixel = pixels[*iptr];
  1073.         addr[0] = pixel;
  1074.         addr[1] = pixel >> 8;
  1075.         addr[2] = pixel >> 16;
  1076.         addr[3] = pixel >> 24;
  1077.         }
  1078.  
  1079. #else /* WITHOUT_SPEEDUPS */
  1080.     
  1081.     int bpl = image->bytes_per_line;
  1082.     unsigned char *data_ptr, *max_data;
  1083.  
  1084.     data = (unsigned char *) image->data;
  1085.     iptr = pixelindex;
  1086. #ifndef WORD64
  1087.     if (*((char *) &RTXpm_byteorderpixel) == image->byte_order) {
  1088.     for (y = 0; y < height; y++) {
  1089.         data_ptr = data;
  1090.         max_data = data_ptr + (width<<2);
  1091.  
  1092.         while (data_ptr < max_data) {
  1093.         *((unsigned long *) data_ptr) = pixels[*(iptr++)];
  1094.         data_ptr += (1<<2);
  1095.         }
  1096.         data += bpl;
  1097.     }
  1098.     } else
  1099. #endif
  1100.     if (image->byte_order == MSBFirst)
  1101.         for (y = 0; y < height; y++) {
  1102.         data_ptr = data;
  1103.         max_data = data_ptr + (width<<2);
  1104.  
  1105.         while (data_ptr < max_data) {
  1106.             pixel = pixels[*(iptr++)];
  1107.  
  1108.             *data_ptr++ = pixel >> 24;
  1109.             *data_ptr++ = pixel >> 16;
  1110.             *data_ptr++ = pixel >> 8;
  1111.             *data_ptr++ = pixel;
  1112.  
  1113.         }
  1114.         data += bpl;
  1115.         }
  1116.       else
  1117.           for (y = 0; y < height; y++) {
  1118.           data_ptr = data;
  1119.           max_data = data_ptr + (width<<2);
  1120.  
  1121.           while (data_ptr < max_data) {
  1122.               pixel = pixels[*(iptr++)];
  1123.  
  1124.               *data_ptr++ = pixel;
  1125.               *data_ptr++ = pixel >> 8;
  1126.               *data_ptr++ = pixel >> 16;
  1127.               *data_ptr++ = pixel >> 24;
  1128.           }
  1129.           data += bpl;
  1130.           }
  1131.  
  1132. #endif /* WITHOUT_SPEEDUPS */
  1133. }
  1134.  
  1135. /*
  1136.  * write pixels into a 16-bits Z image data structure
  1137.  */
  1138.  
  1139. static void
  1140. SetImagePixels16(image, width, height, pixelindex, pixels)
  1141.     XImage *image;
  1142.     unsigned int width;
  1143.     unsigned int height;
  1144.     unsigned int *pixelindex;
  1145.     Pixel *pixels;
  1146. {
  1147.     unsigned char *data;
  1148.     unsigned int *iptr;
  1149.     int y;
  1150.  
  1151. #ifdef WITHOUT_SPEEDUPS
  1152.  
  1153.     int x;
  1154.     unsigned char *addr;
  1155.  
  1156.     data = (unsigned char *) image->data;
  1157.     iptr = pixelindex;
  1158.     if (image->byte_order == MSBFirst)
  1159.     for (y = 0; y < height; y++)
  1160.         for (x = 0; x < width; x++, iptr++) {
  1161.         addr = &data[ZINDEX16(x, y, image)];
  1162.         addr[0] = pixels[*iptr] >> 8;
  1163.         addr[1] = pixels[*iptr];
  1164.         }
  1165.     else
  1166.     for (y = 0; y < height; y++)
  1167.         for (x = 0; x < width; x++, iptr++) {
  1168.         addr = &data[ZINDEX16(x, y, image)];
  1169.         addr[0] = pixels[*iptr];
  1170.         addr[1] = pixels[*iptr] >> 8;
  1171.         }
  1172.  
  1173. #else /* WITHOUT_SPEEDUPS */
  1174.  
  1175.     Pixel pixel;
  1176.  
  1177.     int bpl=image->bytes_per_line;
  1178.     unsigned char *data_ptr,*max_data;
  1179.     
  1180.     data = (unsigned char *) image->data;
  1181.     iptr = pixelindex;
  1182.     if (image->byte_order == MSBFirst)
  1183.       for (y = 0; y < height; y++) {
  1184.           data_ptr = data;
  1185.           max_data = data_ptr + (width<<1);
  1186.  
  1187.           while (data_ptr < max_data) {
  1188.           pixel = pixels[*(iptr++)];
  1189.  
  1190.           data_ptr[0] = pixel >> 8;
  1191.           data_ptr[1] = pixel;
  1192.  
  1193.           data_ptr+=(1<<1);
  1194.           }
  1195.           data += bpl;
  1196.       }
  1197.       else
  1198.       for (y = 0; y < height; y++) {
  1199.           data_ptr  = data;
  1200.           max_data = data_ptr + (width<<1);
  1201.  
  1202.           while (data_ptr < max_data) {
  1203.           pixel = pixels[*(iptr++)];
  1204.  
  1205.           data_ptr[0] = pixel;
  1206.           data_ptr[1] = pixel >> 8;
  1207.  
  1208.           data_ptr+=(1<<1);
  1209.           }
  1210.           data += bpl;
  1211.       }
  1212.  
  1213. #endif /* WITHOUT_SPEEDUPS */
  1214. }
  1215.  
  1216. /*
  1217.  * write pixels into a 8-bits Z image data structure
  1218.  */
  1219.  
  1220. static void
  1221. SetImagePixels8(image, width, height, pixelindex, pixels)
  1222.     XImage *image;
  1223.     unsigned int width;
  1224.     unsigned int height;
  1225.     unsigned int *pixelindex;
  1226.     Pixel *pixels;
  1227. {
  1228.     char *data;
  1229.     unsigned int *iptr;
  1230.     int y;
  1231.  
  1232. #ifdef WITHOUT_SPEEDUPS
  1233.  
  1234.     int x;
  1235.  
  1236.     data = image->data;
  1237.     iptr = pixelindex;
  1238.     for (y = 0; y < height; y++)
  1239.     for (x = 0; x < width; x++, iptr++)
  1240.         data[ZINDEX8(x, y, image)] = pixels[*iptr];
  1241.  
  1242. #else /* WITHOUT_SPEEDUPS */
  1243.  
  1244.     int bpl = image->bytes_per_line;
  1245.     char *data_ptr,*max_data;
  1246.  
  1247.     data = image->data;
  1248.     iptr = pixelindex;
  1249.  
  1250.     for (y = 0; y < height; y++) {
  1251.     data_ptr = data;
  1252.     max_data = data_ptr + width;
  1253.  
  1254.     while (data_ptr < max_data)
  1255.         *(data_ptr++) = pixels[*(iptr++)];
  1256.  
  1257.     data += bpl;
  1258.     }
  1259.  
  1260. #endif /* WITHOUT_SPEEDUPS */
  1261. }
  1262.  
  1263. /*
  1264.  * write pixels into a 1-bit depth image data structure and **offset null**
  1265.  */
  1266.  
  1267. static void
  1268. SetImagePixels1(image, width, height, pixelindex, pixels)
  1269.     XImage *image;
  1270.     unsigned int width;
  1271.     unsigned int height;
  1272.     unsigned int *pixelindex;
  1273.     Pixel *pixels;
  1274. {
  1275.     if (image->byte_order != image->bitmap_bit_order)
  1276.     SetImagePixels(image, width, height, pixelindex, pixels);
  1277.     else {
  1278.     unsigned int *iptr;
  1279.     int y;
  1280.     char *data;
  1281.  
  1282. #ifdef WITHOUT_SPEEDUPS
  1283.  
  1284.     int x;
  1285.  
  1286.     data = image->data;
  1287.     iptr = pixelindex;
  1288.     if (image->bitmap_bit_order == MSBFirst)
  1289.         for (y = 0; y < height; y++)
  1290.         for (x = 0; x < width; x++, iptr++) {
  1291.             if (pixels[*iptr] & 1)
  1292.             data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7);
  1293.             else
  1294.             data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7));
  1295.         }
  1296.     else
  1297.         for (y = 0; y < height; y++)
  1298.         for (x = 0; x < width; x++, iptr++) {
  1299.             if (pixels[*iptr] & 1)
  1300.             data[ZINDEX1(x, y, image)] |= 1 << (x & 7);
  1301.             else
  1302.             data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7));
  1303.         }
  1304.  
  1305. #else /* WITHOUT_SPEEDUPS */
  1306.  
  1307.     char value;
  1308.     char *data_ptr, *max_data;
  1309.     int bpl = image->bytes_per_line;
  1310.     int diff, count;
  1311.  
  1312.     data = image->data;
  1313.     iptr = pixelindex;
  1314.  
  1315.     diff = width & 7;
  1316.     width >>= 3;
  1317.  
  1318.     if (image->bitmap_bit_order == MSBFirst)
  1319.         for (y = 0; y < height; y++) {
  1320.         data_ptr = data;
  1321.         max_data = data_ptr + width;
  1322.         while (data_ptr < max_data) {
  1323.             value=0;
  1324.  
  1325.             value=(value<<1) | (pixels[*(iptr++)] & 1);
  1326.             value=(value<<1) | (pixels[*(iptr++)] & 1);
  1327.             value=(value<<1) | (pixels[*(iptr++)] & 1);
  1328.             value=(value<<1) | (pixels[*(iptr++)] & 1);
  1329.             value=(value<<1) | (pixels[*(iptr++)] & 1);
  1330.             value=(value<<1) | (pixels[*(iptr++)] & 1);
  1331.             value=(value<<1) | (pixels[*(iptr++)] & 1);
  1332.             value=(value<<1) | (pixels[*(iptr++)] & 1);
  1333.  
  1334.             *(data_ptr++) = value;
  1335.         }
  1336.         if (diff) {
  1337.             value = 0;
  1338.             for (count = 0; count < diff; count++) {
  1339.             if (pixels[*(iptr++)] & 1) 
  1340.                 value |= (0x80>>count);
  1341.             }
  1342.             *(data_ptr) = value;              
  1343.         }
  1344.         data += bpl;
  1345.         }
  1346.     else
  1347.         for (y = 0; y < height; y++) {
  1348.         data_ptr = data;
  1349.         max_data = data_ptr + width;
  1350.         while (data_ptr < max_data) {
  1351.             value=0;
  1352.             iptr+=8;
  1353.  
  1354.             value=(value<<1) | (pixels[*(--iptr)] & 1);
  1355.             value=(value<<1) | (pixels[*(--iptr)] & 1);
  1356.             value=(value<<1) | (pixels[*(--iptr)] & 1);
  1357.             value=(value<<1) | (pixels[*(--iptr)] & 1);
  1358.             value=(value<<1) | (pixels[*(--iptr)] & 1);
  1359.             value=(value<<1) | (pixels[*(--iptr)] & 1);
  1360.             value=(value<<1) | (pixels[*(--iptr)] & 1);
  1361.             value=(value<<1) | (pixels[*(--iptr)] & 1);
  1362.  
  1363.             iptr+=8;
  1364.             *(data_ptr++) = value;              
  1365.         }
  1366.         if (diff) {
  1367.             value=0;
  1368.             for (count = 0; count < diff; count++) {
  1369.             if (pixels[*(iptr++)] & 1) 
  1370.                 value |= (1<<count);
  1371.             }
  1372.             *(data_ptr) = value;              
  1373.         }
  1374.         data += bpl;
  1375.         }
  1376.  
  1377. #endif /* WITHOUT_SPEEDUPS */
  1378.     }
  1379. }
  1380.  
  1381. int
  1382. XpmCreatePixmapFromXpmImage(display, d, image,
  1383.                 pixmap_return, shapemask_return, attributes)
  1384.     Display *display;
  1385.     Drawable d;
  1386.     XpmImage *image;
  1387.     Pixmap *pixmap_return;
  1388.     Pixmap *shapemask_return;
  1389.     XpmAttributes *attributes;
  1390. {
  1391.     XImage *ximage, *shapeimage;
  1392.     int ErrorStatus;
  1393.  
  1394.     /* initialize return values */
  1395.     if (pixmap_return)
  1396.     *pixmap_return = 0;
  1397.     if (shapemask_return)
  1398.     *shapemask_return = 0;
  1399.  
  1400.     /* create the ximages */
  1401.     ErrorStatus = XpmCreateImageFromXpmImage(display, image,
  1402.                          &ximage, &shapeimage,
  1403.                          attributes);
  1404.     if (ErrorStatus < 0)
  1405.     return (ErrorStatus);
  1406.  
  1407.     /* create the pixmaps and destroy images */
  1408.     if (ximage) {
  1409.     xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
  1410.     XDestroyImage(ximage);
  1411.     }
  1412.     if (shapeimage) {
  1413.     xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
  1414.     XDestroyImage(shapeimage);
  1415.     }
  1416.     return (ErrorStatus);
  1417. }
  1418.